#/usr/bin/env python
"""
Name: Tank Wars
Author: Hamid Tora, Amin Tora
Date: 05/06/2013
Description: Tank Wars game for ISA 681 course 2013
File: tankwars.py
"""

# ---------- Import Required Modules ----------

import pygame, sys, os, math, time, string, client
from pygame.locals import *

# Print warning message if the font or sound modules are not available

if not pygame.font: print 'Warning, fonts disabled'
if not pygame.mixer: print 'Warning, sound disabled'


# ---------- Define Function to Load Images ----------

def load_image(name, colorkey=None):
	fullname = os.path.join('data', name)
    	try:
        	image = pygame.image.load(fullname)
    	except pygame.error, message:
        	print 'Cannot load image:', fullname
        	raise SystemExit, message
    	image = image.convert()
    	if colorkey is not None:
        	if colorkey is -1:
            		colorkey = image.get_at((0,0))
        	image.set_colorkey(colorkey, RLEACCEL)
    	return image, image.get_rect()

# ---------- Define Function to Load Sounds ----------

def load_sound(name):
	class NoneSound:
        	def play(self): pass
    	if not pygame.mixer or not pygame.mixer.get_init():
        	return NoneSound()
    	fullname = os.path.join('data', name)
    	try:
        	sound = pygame.mixer.Sound(fullname)
    	except pygame.error, message:
        	print 'Cannot load sound:', fullname
        	raise SystemExit, message
    	return sound

# ---------- Define Main Title Object  ----------


class MainTitle(pygame.sprite.Sprite):

	def __init__(self):
		# Invoke Sprite initializer
        	pygame.sprite.Sprite.__init__(self)
        	self.image, self.rect = load_image('tankwars1.png')
        	
		screen = pygame.display.get_surface()
		self.screen = screen
        	self.area = screen.get_rect()

		self.rect = self.image.get_rect()
		self.rect.center = (512,0)

		# Initialize values for bouncing effect
		self.dx = 1
		self.dy = 1
		self.c = 0

	def update(self):
		# Update the Main Title sprite
		if (self.c < 600):
			self._bounceTitle()
			self.c += 1

	def _bounceTitle(self):
		# Drop the Main Title and bounce it 
		self.rect.centery += self.dy
		self._checkBounds()
	
	def _checkBounds(self):
		if self.rect.bottom >= 300:
			self.dy *= -1
		if self.rect.top <= -150:
			self.dy *= -1

# ---------- Define Options Menu Object  ----------

class Option(pygame.sprite.Sprite):

	hovered = False
	
	def __init__(self, filename, pos):
		# Invoke Sprite initializer
		pygame.sprite.Sprite.__init__(self)
                self.file = filename
		self.set_rect()
		self.screen = pygame.display.get_surface()
                self.area = self.screen.get_rect()
		self.rect = self.image.get_rect()
		self.pos = pos
                self.rect.center = self.pos
                self.clicked = False 

	def set_rect(self):
		if self.hovered:
                        self.image, self.rect = load_image(self.file + "_over.png",-1)
                else:
                        self.image, self.rect = load_image(self.file + ".png", -1)
	
	def draw(self):
		self.set_rect()
		self.area = self.screen.get_rect()
                self.rect = self.image.get_rect()
		self.rect.center = self.pos


# ---------- Define Tank Cut-Scene Sprite Object  ----------

class TankCutSceneSprite(pygame.sprite.Sprite):

	def __init__(self, filename, pos):
		# Invoke Sprite initializer
		pygame.sprite.Sprite.__init__(self)
		self.image, self.rect = load_image(filename)

		screen = pygame.display.get_surface()
		self.screen = screen
		self.area = screen.get_rect()
		self.rect = self.image.get_rect()
		self.pos = pos
		self.rect.center = self.pos
		self.file = filename
		self.dx = 1

	def update(self):
		# Update Tank Cut-Scene Sprite
		self._moveTank()

	def _moveTank(self):
                # Move Tank Cut-Scene across screen
		self.rect.centerx += self.dx

# ---------- Define Tank Sprite Object  ----------

class TankSprite(pygame.sprite.Sprite):

        def __init__(self, screen, filename, pos):
            # Invoke Sprite initializer
            pygame.sprite.Sprite.__init__(self)
            self.image, self.rect = load_image(filename, -1)
            
            self.screen = screen
            self.area = screen.get_rect()
            self.rect = self.image.get_rect()
            self.pos = pos
            self.rect.center = self.pos
            self.file = filename
        
            self.dx = 0
    
        def update(self):
            # Update Tank Sprite
            self._moveTank()

        def _moveTank(self):
            # Move Tank based on input
          self.rect.centerx += self.dx

# ---------- Define Status Banner Object  ----------
 
class StatusBanner(pygame.sprite.Sprite):
 
        def __init__(self, screen, filename, pos, p1stats, p2stats):
            # Invoke Sprite initializer
            pygame.sprite.Sprite.__init__(self)
            self.image, self.rect = load_image(filename)
            self.screen = screen
            self.area = screen.get_rect()
            self.rect = self.image.get_rect()
            self.pos = pos
            self.rect.center = self.pos
            self.file = filename

            self.p1fuel = p1stats[0]
            self.p1life = p1stats[1]
            self.p1weapons = p1stats[2]

            self.p2fuel = p2stats[0]
            self.p2life = p2stats[1]
            self.p2weapons = p2stats[2]

        def update(self):

            # Update status bar based on input
            self.drawStatus()
            
        def drawStatus(self):

            # Render text onto screen
            font = pygame.font.Font(None, 24)

            # Update Player-1 Stats
            p1_fuel_text = font.render(self.p1fuel, 1, (255, 0, 0) )
            p1_life_text = font.render(self.p1life, 1, (255, 0, 0) )
            p1_weapons_text = font.render(self.p1weapons, 1, (255, 0, 0) )
        
            self.image.blit(p1_fuel_text, (50, 72))
            self.image.blit(p1_life_text, (45, 35))
            self.image.blit(p1_weapons_text, (175, 72))

            # Update Player-2 Stats
            p2_fuel_text = font.render(self.p2fuel, 1, (255, 0, 0) )
            p2_life_text = font.render(self.p2life, 1, (255, 0, 0) )
            p2_weapons_text = font.render(self.p2weapons, 1, (255, 0, 0) )

            self.image.blit(p2_fuel_text, (990, 72)) 
            self.image.blit(p2_life_text, (980, 38))
            self.image.blit(p2_weapons_text, (770, 70))

        
# Draws text message onto the screen
def drawText(screen, text, pos):
    
        font = pygame.font.Font(None, 24)
        message = font.render(text, 1, (0, 0, 0) )
            
        screen.blit(message, pos)
            
        pygame.display.flip()


# ---------- Define Play Function  ----------
class Level():

        def __init__(self, screen):

            self.screen = screen
            self.going = True
            self.p1stats = ["250", "100%", "S: 100, M: 10, L: 2"]
            self.p2stats = ["250", "100%", "S: 100, M: 10, L: 2"]

            # Instantiate Tank and Status Banner sprites
            self.p1_tank = TankSprite(screen,"tanksprite_p1.png", (100,700))
            self.p2_tank = TankSprite(screen,"tanksprite_p2.png", (900,700))
            self.statusbanner = StatusBanner(screen, "status_banner.png", (512,50), self.p1stats, self.p2stats)

        # Primary function to ask user for input
        def userInput(self):
                ask_user = True

        # Primary function to play main level
        def play(self):

                # Define input buffer used to store keyboard input
                input_buffer = []

                # Define boolean variables for user input controls
                user_asked = False
                done = False
                
           
                # Define level landscape
                self.landscape, self.landscape_rect = load_image("background.png")
                self.landscape_rect = self.landscape.get_rect()
                size = (width, height) = self.landscape.get_size()

                # Initializes pygame settings
                pygame.mouse.set_visible(1)

                # Creates the background image
                background = pygame.Surface(self.screen.get_size())
                background = background.convert()
                background.fill((0,0,0))

            
                while self.going:

                    for event in pygame.event.get():
                        if event.type == pygame.QUIT:
                            pygame.quit()
                            sys.exit()
                        elif event.type == KEYDOWN and event.key == K_ESCAPE:
                            pygame.quit()
                            sys.exit()
                        elif event.type == KEYDOWN and user_asked == True:
                            while not done: 
                                if  event.key == K_BACKSPACE:
                                    input_buffer = input_buffer[0:1]
                                elif event.key == K_RETURN:
                                    ask_user = False
                                    done = True
                                elif event.key <= 3:
                                    input_buffer.append(chr(event.key))
                        elif event.type == KEYDOWN:
                            return event.key
                        else:
                            pass

                    # Initializes pygame settings
                    pygame.mouse.set_visible(1)
                    
                    # Displays the background
                    self.screen.blit(background, (0,0))
                    self.screen.blit(self.landscape, self.landscape_rect)

                    # Draw all spritesobject
                    allsprites = pygame.sprite.RenderPlain((self.p1_tank, self.p2_tank, self.statusbanner))

                    # Invoke client connection to server
                    # client.connect()

                    allsprites.update()
                    allsprites.draw(self.screen)
                    pygame.display.flip()
                    
                    drawText(self.statusbanner.image, "P1 - Angle?: " + string.join(input_buffer, ""), (350, 15)) 
                    user_asked = True
                    drawText(self.statusbanner.image, "P1 - Angle?: " + string.join(input_buffer, ""), (350, 15)) 
# ---------- Define Main Function ----------

def main():

	"""
	This function is called when the program starts.
	It initializes all required variables and runs main
	loop until the function returns.
	"""	
	# Initializes pygame settings
 
	pygame.init()
	window = pygame.display.set_mode((1024,768))
	pygame.display.set_caption('Tank Wars')
	screen = pygame.display.get_surface()
    	pygame.mouse.set_visible(1)


	# Creates the background image

	background = pygame.Surface(screen.get_size())
	background = background.convert()
	background.fill((0, 0, 0))

	# Displays the background
	screen.blit(background, (0, 0))
	pygame.display.flip()

	# Prepare Game Objects
    	
	# Initialize clock
	clock = pygame.time.Clock()
    	
	# Load menu sounds
	explosion_sound1 = load_sound('explosion1.wav')
	explosion_sound2 = load_sound('explosion2.wav')

	# Play background sound	
	while pygame.mixer.music.get_busy():
		pygame.time.Clock().tick(10)
	explosion_sound1.play()

	# initalize object
    	maintitle = MainTitle()
        options = [Option("start_menu", (512, 350)), Option("settings_menu", (512,450)), Option("quit_menu", (512,550))]
	hovertank = TankCutSceneSprite("hovertank_right.png", (0, 700))
        level = Level(screen)

	# Draw all spritesobject
        allsprites = pygame.sprite.RenderPlain((maintitle, options[0], options[1], options[2]), hovertank)

	# Main Loop
    	while 1:
                # Make sure game does not run > 60 FPS
        	clock.tick(60)

		# Menu Loop
		pygame.event.pump()
		for option in options:
			# Check for collision and return mouse position
                	if option.rect.collidepoint(pygame.mouse.get_pos()):
                        	option.hovered = True
                	else:
                        	option.hovered = False
			option.draw()

		pygame.display.update()

    		# Handle Input Events
        	for event in pygame.event.get():
            		if event.type == QUIT:
                		return
            		elif event.type == KEYDOWN and event.key == K_ESCAPE:
                		return
			elif event.type == MOUSEBUTTONDOWN:
				for option in options:
					if option.rect.collidepoint(pygame.mouse.get_pos()):
						option.clicked = True
                                                if option.file == "quit_menu" or option.file == "quit_menu_over":
                                                    explosion_sound2.play()
                                                    return
                                                elif option.file == "start_menu" or option.file == "start_menu_over":
                                                    explosion_sound2.play()
                                                    explosion_sound1.stop()
                                                    level.play()
                                                elif option.file == "settings_menu" or option.file == "settings_menu_over":
                                                    explosion_sound2.play()
                                                    explosion_sound1.stop()
					else:
						option.clicked = False	
			else:
				pass


                # Update all sprites
        	allsprites.update()

    		# Draw Everything
        	screen.blit(background, (0, 0))
        	allsprites.draw(screen)
        	pygame.display.flip()

# ---------- End Main Function ----------


# This calls the 'main' function when this script is executed
if __name__ == '__main__': main()



